package android.slc.icr.core.room.manager;

import android.slc.icr.core.constant.IcrConstants;
import android.slc.icr.core.entity.IcrChartRoom;
import android.slc.icr.core.entity.IcrMessage;
import android.slc.icr.core.room.studio.AbsChartRoomStudio;
import android.slc.icr.core.utils.IcrMessageUtils;
import android.slc.icr.service.IcrMessageRemoteService;
import android.slc.icr.service.IcrPersistenceService;
import android.slc.utils.commonlibrary.GsonUtils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.Scheduler;
import io.reactivex.rxjava3.schedulers.Schedulers;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author slc
 * @date 2022/05/10 下午 1:10
 */
public abstract class AbsChartRoomManager<R extends AbsChartRoomStudio> implements IChartRoomManager, IDestroyRoomListener {
    protected final Logger logger = LoggerFactory.getLogger(AbsChartRoomManager.class);

    //订阅线程调度
    public static final Scheduler OBSERVE_ON_SCHEDULER = Schedulers.newThread();
    //聊天室 根据聊天室id进行的绑定
    protected final Map<String, R> chartRoomByRoomIdMap = new ConcurrentHashMap<>();
    protected ObservableEmitter<IcrMessage> messageEmitter;
    //远程消息服务
    private IcrMessageRemoteService icrMessageRemoteService;
    //持久化服务
    private IcrPersistenceService icrPersistenceService;

    public AbsChartRoomManager() {
        Observable.create(new ObservableOnSubscribe<IcrMessage>() {
                    @Override
                    public void subscribe(@NonNull ObservableEmitter<IcrMessage> emitter) {
                        AbsChartRoomManager.this.messageEmitter = emitter;
                    }
                }).subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(OBSERVE_ON_SCHEDULER)
                .subscribe(this);
    }

    @Override
    public void setMustParam(IcrMessageRemoteService icrMessageRemoteService, IcrPersistenceService icrPersistenceService) {
        this.icrMessageRemoteService = icrMessageRemoteService;
        this.icrPersistenceService = icrPersistenceService;
    }

    protected IcrMessageRemoteService getIcrMessageRemoteService() {
        return icrMessageRemoteService;
    }

    protected IcrPersistenceService getIcrPersistenceService() {
        return icrPersistenceService;
    }

    @Override
    public void receiveMessage(IcrMessage message) {
        if (message != null) {
            messageEmitter.onNext(message);
        }
    }

    @Override
    public void onNext(IcrMessage message) {
        try {
            onMessage(message);
        } catch (Exception e) {
            logger.error("onMessage：", e);
        }
    }

    //此处处理消息
    @Override
    public void onMessage(IcrMessage message) {
        String sendId = message.getSender();
        String action = message.getAction();
        String roomId = message.getRelateId();
        if (!IcrMessageUtils.checkIcrMessage(message)) {
            //消息检查不通过 直接通知用户
            if (StrUtil.isNotEmpty(sendId)) {
                //此处可能存在roomId为空
                String roomIdTemp = null;
                if (StringUtils.isEmpty(roomId)) {
                    roomIdTemp = getRoomMsgType();
                } else {
                    roomIdTemp = roomId;
                }
                IcrMessageUtils.sendActionMissingParam(icrMessageRemoteService, action, createMustInfo(roomIdTemp, sendId, IcrChartRoom.builder().setRoomId(roomIdTemp).build()));
            }
            return;
        }
        R chartRoomStudio = chartRoomByRoomIdMap.get(roomId);
        if (IcrConstants.Action.ACTION_CHART_ROOM_CREATE.equals(action)) {
            //创建房间
            if (chartRoomStudio != null) {
                //通知房间存在
                if (Objects.equals(chartRoomStudio.getIcrChartRoom().getCreateUserId(), sendId)) {
                    getIcrMessageRemoteService().sendMessage(fillMustInfo(chartRoomStudio.getIcrChartRoomId(), sendId, IcrMessage.newBuilder()
                            .setAction(IcrConstants.Action.ACTION_CHART_ROOM_CREATE_EXISTED)
                            .setContent(GsonUtils.toJson(chartRoomStudio.getIcrChartRoom()))
                            .build(), chartRoomStudio.getIcrChartRoom()));
                } else {
                    //通知房间被占用
                    getIcrMessageRemoteService().sendMessage(fillMustInfo(chartRoomStudio.getIcrChartRoomId(), sendId, IcrMessage.newBuilder()
                            .setAction(IcrConstants.Action.ACTION_CHART_ROOM_CREATE_USING)
                            .setContent(GsonUtils.toJson(chartRoomStudio.getIcrChartRoom()))
                            .build(), chartRoomStudio.getIcrChartRoom()));
                }
                return;
            }
            IcrChartRoom icrChartRoom = formatIcrChartRoom(message.getContent());
            if (icrChartRoom == null || !icrChartRoom.selfTest()) {
                //创建房间缺少参数
                IcrMessageUtils.sendActionMissingParam(getIcrMessageRemoteService(), action,
                        createMustInfo(roomId, sendId, icrChartRoom));
                return;
            }
            //创建聊天室 通知创建成功
            chartRoomStudio = createChartRoomStudio(icrChartRoom);
            chartRoomByRoomIdMap.put(icrChartRoom.getRoomId(), chartRoomStudio);
            chartRoomStudio.onOperateEvent(message);
        }
        if (chartRoomStudio == null) {
            //当操作聊天室但聊天室不存在时，则直接通知用户
            IcrMessageUtils.sendChartRoomIllicit(getIcrMessageRemoteService(), action,
                    IcrMessageUtils.STR_DOES_NOT_EXIST, createMustInfo(roomId, sendId, IcrChartRoom.builder().setRoomId(roomId).build()));
            return;
        }
        switch (action) {
            //销毁
            case IcrConstants.Action.ACTION_CHART_ROOM_DESTROY:
                //缺少权限
                if (!Objects.equals(chartRoomStudio.getIcrChartRoom().getCreateUserId(), sendId)) {
                    IcrMessageUtils.sendChartRoomPermissionDenied(getIcrMessageRemoteService(), action,
                            createMustInfo(chartRoomStudio.getIcrChartRoomId(), sendId, IcrChartRoom.builder().setRoomId(chartRoomStudio.getIcrChartRoomId()).build()));
                    break;
                }
                //销毁完成，移除所有消息
                chartRoomByRoomIdMap.remove(chartRoomStudio.getIcrChartRoomId());
                chartRoomStudio.onOperateEvent(message);
                chartRoomStudio.destroy();
                break;
            //消息
            case IcrConstants.Action.ACTION_RTC_SEND_MSG_CHART_ROOM:
                //加入房间
                //离开房间
            case IcrConstants.Action.ACTION_CHART_ROOM_JOIN:
            case IcrConstants.Action.ACTION_CHART_ROOM_LEFT:
                chartRoomStudio.onOperateEvent(message);
                break;
        }
    }

    @Override
    public void onDestroyRoom(String sendId, String roomId) {
        onMessage(IcrMessage.newBuilder()
                .setSender(sendId)
                .setRelateId(roomId)
                .setRelate(getRoomMsgType())
                .setAction(IcrConstants.Action.ACTION_CHART_ROOM_DESTROY)
                .build());
    }

    /**
     * 格式化聊天室房间信息
     *
     * @param icrChartRoomJson
     * @return
     */
    protected IcrChartRoom formatIcrChartRoom(String icrChartRoomJson) {
        return GsonUtils.fromJson(icrChartRoomJson, IcrChartRoom.class);
    }

    /**
     * 创建聊天室
     *
     * @param icrChartRoom
     * @return
     */
    protected abstract R createChartRoomStudio(IcrChartRoom icrChartRoom);

    protected List<IcrChartRoom> getChartRoomList() {
        Collection<R> chartRoomStudioCollection = chartRoomByRoomIdMap.values();
        final List<IcrChartRoom> icrChartRoomList = new ArrayList<>();
        CollectionUtil.forEach(chartRoomStudioCollection, new CollUtil.Consumer<R>() {
            @Override
            public void accept(R value, int index) {
                icrChartRoomList.add(value.getIcrChartRoom());
            }
        });
        return icrChartRoomList;
    }

    @Override
    public List<IcrChartRoom> getOnlyReadChartRoomList() {
        final List<IcrChartRoom> icrChartRoomList = getChartRoomList();
        String icrChartRoomListStr = GsonUtils.toJson(icrChartRoomList);
        List<IcrChartRoom> icrChartRoomListResult = GsonUtils.fromJson(icrChartRoomListStr, GsonUtils.getListType(IcrChartRoom.class));
        if (icrChartRoomListResult == null) {
            icrChartRoomListResult = new ArrayList<>();
        }
        return icrChartRoomListResult;
    }

    /**
     * 根据聊天室id查询聊天室
     *
     * @param roomId
     * @return
     */
    protected IcrChartRoom findChartRoomByRoomId(String roomId) {
        R chartRoomStudio = chartRoomByRoomIdMap.get(roomId);
        if (chartRoomStudio != null) {
            return chartRoomStudio.getIcrChartRoom();
        }
        return null;
    }

    /**
     * 根据聊天室id查询聊天室信息
     *
     * @param roomId
     * @return
     */
    @Override
    public IcrChartRoom findOnlyReadChartRoomByRoomId(String roomId) {
        IcrChartRoom icrChartRoom = findChartRoomByRoomId(roomId);
        if (icrChartRoom == null) {
            return null;
        }
        String icrChartRoomStr = GsonUtils.toJson(icrChartRoom);
        IcrChartRoom icrChartRoomResult = GsonUtils.fromJson(icrChartRoomStr, IcrChartRoom.class);
        return icrChartRoomResult;
    }

    //---------------消息发送 start-------------------------//

    /**
     * 填充必要的信息
     *
     * @param sendId
     * @param receiveId
     * @param icrMessage
     * @param icrChartRoom
     * @return
     */
    protected IcrMessage fillMustInfo(String sendId, String receiveId, IcrMessage icrMessage, IcrChartRoom icrChartRoom) {
        icrMessage.setSender(sendId);
        icrMessage.setReceiver(receiveId);
        icrMessage.setRelate(getRoomMsgType());
        if (icrChartRoom != null) {
            icrMessage.setRelateId(icrChartRoom.getRoomId());
        }
        return icrMessage;
    }

    /**
     * 创建必要信息
     *
     * @param sendId
     * @param receiveId
     * @param icrChartRoom
     * @return
     */
    protected IcrMessage createMustInfo(String sendId, String receiveId, IcrChartRoom icrChartRoom) {
        return fillMustInfo(sendId, receiveId, IcrMessage.newBuilder().build(), icrChartRoom);
    }

    //---------------消息发送 end-------------------------//
}
